// 线程池声明文件
#ifndef THREADPOOL_HPP
#define THREADPOOL_HPP
#include <iostream>
#include <vector>
#include <functional>
#include <thread>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <future>
#include <stdexcept>

template <typename T>
class Threadpool
{
private:
	std::vector<std::thread> workers;				// 工作线程容器
	std::queue<std::function<void()>> tasks;		// 任务队列（存储可调用对象）
	std::mutex queueMutex;							// 任务队列互斥锁
	std::condition_variable condition;				// 线程同步条件变量
	bool stop_flag = false;

	// 不暴露的接口辅助函数
	void workerThread();		// 工作线程执行的主循环

public:
	Threadpool(size_t numThread);
	~Threadpool();

	// 暴露出去的接口函数   运行调用
	// 任务入队接口（完美转发参数）
	// template <typename F, typename... Args>
	// auto enqueueTask(F&& f, Args&&... args) -> std::future<T>;
	// auto enqueueTask(F&& f, Args&&... args) -> std::future<std::invoke_result_t<F, Args...>>;
	
	template <typename F, typename... Args>
	auto enqueueTask(F&& f, Args&&... args) -> std::future<std::invoke_result_t<F, Args...>> {
		using ReturnType = std::invoke_result_t<F, Args...>;

		auto task = std::make_shared<std::packaged_task<ReturnType()>>(
			std::bind(std::forward<F>(f), std::forward<Args>(args)...)
		);

		std::future<ReturnType> result = task->get_future();
		{
			std::lock_guard<std::mutex> lock(queueMutex);
			if (stop_flag) {
				throw std::runtime_error("Threadpool is stopped, cannot enqueue tasks.");
			}
			tasks.emplace([task]() { (*task)(); });
		}
		condition.notify_one();
		return result;
	}
	// 安全停止线程池的接口
	void stop() {
		{
			std::lock_guard<std::mutex> lock(queueMutex);
			stop_flag = true;
		}
		condition.notify_all();		// 唤醒所有线程
		for (auto& worker : workers) {
			worker.join();		// 等待所有线程结束 阻塞一下主线程达到等待其他线程的效果
		}
	}
};

#endif
